<?php
/**
 * Created by PhpStorm.
 * User: jjj
 * Date: 2017/8/10
 * Time: 16:05
 */

namespace app\admin\behaviour;


use app\admin\controller\Account;
use app\admin\model\ApiResponse;
use app\admin\model\SysAdmin;
use think\Cache;
use think\cache\Driver;
use think\Env;
use think\Request;

class AdminAuth
{
    /**
     * 公共接口配置
     * 参数为 [
     *  <controller> => [
     *        <action> => true
     *    ]
     * ]
     * @var array
     */
    private $publicList = [
        'Account' => [
            'login' => true,
            'customer_service_login' => true,
        ]
    ];

    private $permitAll = [
        'Alioss' => true,
        'Account' => true,
        'Netease' => true,
        'common' => true,
    ];

    /**
     * 检查请求是否需要登录
     * @param Request $request
     * @return bool
     */
    private function checkPublic(Request $request) {

        $ctrl = $request->controller();
        $act = $request->action();

        return $this->publicList[$ctrl][$act] ?? false;
    }

    private function checkPermitAll(Request $request) {
        $ctrl = $request->controller();
        return $this->permitAll[$ctrl] ?? false;
    }

    /**
     * 检查token
     * @param Request $request
     * @return bool|int
     */
    private function checkAccountToken(Request $request) {

        $adminId = $request->header('uid');
        if (null === $adminId) $adminId = input('uid');

        $token = $request->header('token');
        if (null === $token) $token = input('token');

        $adminId = (int) $adminId;
        if (self::chkToken($adminId, $token)) {
            return $adminId;
        }

        return false;

    }

    /**
     * 执行登录授权检查
     * @param Request $request
     */
    public function run(Request $request) {

        // 检查：公共接口则返回，不处理
        if ($this->checkPublic($request)) {
            return;
        }

        // 检查用户token，返回管理员id
        $adminId = $this->checkAccountToken($request);
        if (false == $adminId) {
            ApiResponse::error(ApiResponse::ERR_TOKEN_INVALID,'未登录');
        }

        // 检查权限
        if ( 1 != $adminId && !$this->checkPermitAll($request) ) {
            $uri = '/' . $request->path();
            $admin = SysAdmin::get($adminId);
            $p = $admin->checkPermit($uri);
            if (!$p) {
                ApiResponse::error(ApiResponse::ERR_PERMISSION_DENIED,'没有权限');
            }
        }

        $request->bind('adminId', $adminId);
    }

    public static function setToken($adminId) {
        $token = md5($adminId.':'.microtime(true));
        $expired = Env::get('server.TokenExpired',28800);
        self::getCache()->tag('admin_'.$adminId)->set($token,true, $expired);
        return $token;
    }

    public static function chkToken($adminId, $token) {
        return self::getCache()->tag('admin_'.$adminId)->get($token);
    }

    public static function rmToken($adminId) {
        self::getCache()->rm('admin_'.$adminId);
    }

    private static function getCache() :Driver {
        return Cache::tag('sys_admin_token');
    }
}